package midend;

import midend.IR_Instruction.*;
import midend.IR_Type.*;
import midend.IR_Value.*;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.*;

import static midend.IR_Builder.*;
import static midend.IR_Builder.setbuilderbb;

public class IR_Module {
    StringBuilder stringBuilder;
    private LinkedHashMap<String,IR_FuncBlock> funcmap;
    //private ArrayList<IR_FuncBlock> funcblocks = new ArrayList<>(this.funcmap.values());
    //下面这个 map存放的是定义和后续的赋值
    private HashMap<String, IR_Value> gloabal_Varmap;
    //存放的是定义，确保存储的都是IRglobal类型，赋值需要从gloabal_Varmap里面查询
    private ArrayList<IR_Global_Value> globalVars;
    private String Module_name;
    private static IR_Type Int_i32 = IR_Int32.IR_Int32();
    private static IR_Type Float_float = IR_Float.IR_Float();
    private IR_Type i32Type;
    private IR_Type i1Type;
    private IR_Type floatType;
    private IR_Type voidType;
    private IR_Value i32zero;
    private IR_Value floatZero;
    private int arrayCount = 0;
    private Map<IR_BaseBlock,IR_BaseBlock> bbopt;
    public IR_Module(String module_name) {
        Module_name = module_name;
        this.funcmap = new LinkedHashMap<>();
        this.gloabal_Varmap = new HashMap<>();
        this.globalVars = new ArrayList<>();
        this.stringBuilder = new StringBuilder();
        this.i32Type = IR_Int32.IR_Int32();
        this.i1Type = IR_Int1.IR_Int1();
        this.floatType = IR_Float.IR_Float();
        this.voidType = IR_Void.IR_Void();
        this.i32zero = new IR_Int_Value(0, i32Type);
        this.floatZero = new IR_Float_Value(0.0f);
        Init();
    }

    public void addGlobalvar(IR_Global_Value global){
        globalVars.add(global);
    }

    public ArrayList<IR_Global_Value> getGlobalVars(){
        return this.globalVars;
    }

    public void Init(){
        /*
        ; ModuleID = 'add.c'
           source_filename = "add.c"
         */
        this.stringBuilder = new StringBuilder();
        this.stringBuilder.append("; ModuleID = '").append(this.Module_name).append("'\n");
        this.stringBuilder.append("source_filename = \"").append(this.Module_name).append("\"\n\n");
        //初始化库函数的基本块

        stringBuilder.append("declare i32 @getint()\n");
        stringBuilder.append("declare i32 @getch()\n");
        stringBuilder.append("declare float @getfloat()\n");
        stringBuilder.append("declare i32 @getarray(i32* %0)\n");
        stringBuilder.append("declare i32 @getfarray(float* %0)\n");
        stringBuilder.append("declare void @putint(i32 %0)\n");
        stringBuilder.append("declare void @putch(i32 %0)\n");
        stringBuilder.append("declare void @putarray(i32 %0, i32* %1)\n");
        stringBuilder.append("declare void @putfloat(float %0)\n");
        stringBuilder.append("declare void @putfarray(i32 %0, float* %1)\n");
        stringBuilder.append("declare void @putf(i32* %0, ...)\n");
        stringBuilder.append("declare void @before_main()\n");
        stringBuilder.append("declare void @after_main()\n");
        stringBuilder.append("declare void @_sysy_starttime(i32 %0)\n");
        stringBuilder.append("declare void @_sysy_stoptime(i32 %0)\n");
        stringBuilder.append("declare void @memset(i32*, i32, i32)\n");
        stringBuilder.append("\n");

    }
    //IR_Module module
    public static void IR_Code_To_File(IR_Module module,String path){
        for(IR_FuncBlock func:module.funcmap.values()){
            module.stringBuilder.append(func.code_Gen());
        }
        try{
            BufferedWriter writer = new BufferedWriter(new FileWriter(path));
            writer.write(module.stringBuilder.toString());
            writer.close();
        }catch(IOException e){
            System.err.println("ERROR : Failed to print IR code to file " + path);
        }
    }

    public void Update_stringbuilder(){
        // 打印优化后的ir
        int zz = 0;
        for (IR_FuncBlock function : this.getFuncBlocks()) {
            for (IR_BaseBlock block : function.get_bb_List()) {
                //System.out.println(" " + "Block: " + block.get_ValueName());
                block.setS();
                List<Instruction> instructions = block.get_Instruction_List();
                for (Instruction instruction : instructions) {
                    block.appendln(instruction.toString());
                }
            }
        }
    }
    //添加函数块
    public void add_FunctoModule(IR_FuncBlock func){
        this.funcmap.put(func.get_FuncName(),func);
    }

    //添加全局变量
    public IR_Value add_Var_toGlobal(String name,IR_Type typ){
        //@number =  global i32 1
        IR_Type basetype = new IR_Pointer(typ);
        IR_Value var = new IR_Global_Value(name,basetype);
        this.stringBuilder.append(var.get_ValueName()).append(" = global ").append(typ.get_TypeName()).append(" ");
        return var;
    }

    public void var_Init(IR_Global_Value value,IR_Value constvalue){
        this.gloabal_Varmap.put(value.get_Global_Identity(),constvalue);
        this.stringBuilder.append(constvalue.get_ValueName()).append("\n");
    }

    public IR_FuncBlock get_func_byName(String name) {
        return funcmap.get(name);
    }

    public void array_Init(IR_Global_Value globalVar, List<IR_Value> constValueList) {
        //这里为了处理数组的初始化
        boolean flag = true;
        if (!constValueList.isEmpty()) {
            //如果传入的constValueList不为空，说明指定了初始化值
            if (constValueList.get(0).get_Type() == Float_float) {
                List<Float> initValue = new ArrayList<>();
                for (IR_Value irValueRef : constValueList) {
                    //如果不是0，说明不是zero initializer
                    if (!Objects.equals(irValueRef.get_ValueName(), "0")) {
                        flag = false;
                    }
                    initValue.add(Float.valueOf(irValueRef.get_ValueName()));
                }
                //设置全局变量的初始化值
                IR_Array_Value arrayRef = new IR_Array_Value(globalVar.get_Global_Identity(), Float_float);
                arrayRef.set_Float_Array(initValue);
                arrayRef.setNowtype((IR_Array) ((IR_Pointer)globalVar.get_Type()).get_Base_Type());
                arrayRef.setIs_AllZero(flag);
                this.gloabal_Varmap.put(globalVar.get_Global_Identity(),arrayRef);
            } else if (constValueList.get(0).get_Type() == Int_i32) {
                List<Integer> initValue = new ArrayList<>();
                for (IR_Value irValueRef : constValueList) {
                    if (!Objects.equals(irValueRef.get_ValueName(), "0")) {
                        flag = false;
                    }
                    initValue.add(Integer.valueOf(irValueRef.get_ValueName()));
                }
                IR_Array_Value arrayRef = new IR_Array_Value(globalVar.get_Global_Identity(), Int_i32);
                arrayRef.setNowtype((IR_Array) ((IR_Pointer)globalVar.get_Type()).get_Base_Type());
                arrayRef.set_Int_Array(initValue);
                arrayRef.setIs_AllZero(flag);
                this.gloabal_Varmap.put(globalVar.get_Global_Identity(),arrayRef);
            }
        } else {
            List<Float> initValue = new ArrayList<>();
            IR_Array_Value arrayRef = new IR_Array_Value(globalVar.get_Global_Identity(), Float_float);
            arrayRef.setNowtype((IR_Array) ((IR_Pointer)globalVar.get_Type()).get_Base_Type());
            arrayRef.set_Float_Array(initValue);
            arrayRef.setIs_AllZero(true);
            this.gloabal_Varmap.put(globalVar.get_Global_Identity(),arrayRef);
        }
        if (flag) {
            //如果全部初始化为0，则直接输出zeroinitializer
            this.stringBuilder.append("zeroinitializer").append("\n");
            return;
        }
        //输出初始化值
        IR_Type elementType = ((IR_Pointer)globalVar.get_Type()).get_Base_Type();
        StringBuilder emitStr = new StringBuilder();
        List<Integer> paramList = new ArrayList<>();
        while (elementType instanceof IR_Array) {
            //计算数组的元素个数
            paramList.add(((IR_Array) elementType).get_Array_length());
            elementType = ((IR_Array) elementType).get_Array_Type();
        }
        String typeStr;
        if (elementType == Int_i32) {
            typeStr = Int_i32.get_TypeName();
        } else {
            typeStr = Float_float.get_TypeName();
        }
        //计算数组的维度
        IR_Type thisarray = ((IR_Pointer)globalVar.get_Type()).get_Base_Type();
        //从 0 开始找
        arrayCount = 0;
        //获取信息
        elementType = ((IR_Array)thisarray).get_Array_Type();
        //递归构造数组
        gen_Arrayname(paramList,0,elementType,emitStr,constValueList,typeStr);
        //System.out.println(newemitStr.toString());
        this.stringBuilder.append(emitStr).append("\n");
    }

    public void gen_Arrayname(List<Integer> paralist,int n,IR_Type elementType,StringBuilder emitStr,List<IR_Value> constValueList,String typeStr) {
        //不是最后一维的情况下递归
        if(n != paralist.size() - 1) {
            emitStr.append('[');
            for (int j = 0; j < paralist.get(n); j++) {
                //前面的初始化信息
                emitStr.append(elementType.get_TypeName());
                gen_Arrayname(paralist,n + 1,((IR_Array)elementType).get_Array_Type(),emitStr,constValueList,typeStr);
                if (j != paralist.get(n) - 1) {
                    emitStr.append(",");
                }
            }
            emitStr.append(']');
        }
        else{
            boolean isallzero = true;
            int tmpcount = arrayCount;
            //判断是不是全 0 的默认情况
            for(int j = 0; j < paralist.get(n); j++){
                if (!constValueList.get(tmpcount++).get_ValueName().equals("0")) {
                    isallzero = false;
                    break;
                }
            }
            if(isallzero){
                emitStr.append(" zeroinitializer");
                arrayCount += paralist.get(n);
            }
            else{
                emitStr.append("[");
                for(int j = 0; j < paralist.get(n); j++){
                    emitStr.append(typeStr).append(" " + constValueList.get(arrayCount++).get_ValueName());
                    if(j != paralist.get(n) - 1){
                        emitStr.append(",");
                    }
                }
                emitStr.append("]");
            }
        }
    }

    public ArrayList<IR_FuncBlock> getFuncBlocks() { return new ArrayList<>(this.funcmap.values()); }

    public HashMap<String, IR_Value> get_Gloabal_Varmap(){
        return this.gloabal_Varmap;
    }

    public LinkedHashMap<String,IR_FuncBlock> getFuncmap(){
        return this.funcmap;
    }

    public void buildCallRelation() {
        //清空调用链和被调用链
        for (IR_FuncBlock function : funcmap.values()) {
            function.getCalledList().clear();
            function.getBeCalledList().clear();
        }
        //构造调用链和被调用链
        for (IR_FuncBlock function : funcmap.values()) {
            List<IR_BaseBlock> basicBlocks = function.get_bb_List();
            for (IR_BaseBlock block : basicBlocks) {
                List<Instruction> instructions = block.get_Instruction_List();
                for (Instruction instruction : instructions) {
                    if (instruction instanceof Call_Instruction) {
                        IR_FuncBlock callFunction = ((Call_Instruction) instruction).get_funcBlock();
                        //当调用的函数不是库函数的时候，且此时的 调用链和被调用链没有该函数的时候添加
                        if (!callFunction.isLib() && !callFunction.getBeCalledList().contains(function)) {
                            callFunction.getBeCalledList().add(function);
                        }
                        if (!callFunction.isLib() && !function.getCalledList().contains(callFunction)) {
                            function.getCalledList().add(callFunction);
                        }
                    }
                }
            }
        }
    }
    public void setfuncTail(){
        //设定 函数尾巴，优化尾递归
        for(IR_FuncBlock funcBlock:funcmap.values()){
            //如果该函数是 递归的
            if(funcBlock.isRecursive()){
                for(IR_BaseBlock block:funcBlock.get_bb_List()){
                    for(int i = 0;i < block.get_Instruction_List().size() - 1;i++){
                        Instruction instruction = block.get_Instruction_List().get(i);
                        Instruction instruction1 = block.get_Instruction_List().get(i + 1);
                        //自己递归
                        if(instruction instanceof Call_Instruction && ((Call_Instruction)instruction).get_funcBlock().equals(funcBlock)){
                            //调用完自己之后直接返回  可能存在多个满足条件的，要确保所有的都是尾递归
                            if(instruction1 instanceof Branch_Instruction && !((Branch_Instruction)instruction1).br_type() && ((Branch_Instruction)instruction1).get_block1().equals(funcBlock.getExitBlock()) ){
                                //funcBlock.setTail();
                            }
                            else{
                                return;
                            }
                        }
                    }
                }
                funcBlock.setTail();
            }
        }
    }

    //删除没有调用过的函数
    public void removeNoCallFunc() {
        boolean changed = true;
        ArrayList<IR_FuncBlock> deletdList = new ArrayList<>();
        while(changed){
            deletdList = new ArrayList<>();
            changed = false;
            for(IR_FuncBlock irFuncBlock:this.getFuncBlocks()){
                if(!"main".equals(irFuncBlock.get_FuncName()) && irFuncBlock.getBeCalledList().size() == 0){
                    deletdList.add(irFuncBlock);
                    changed = true;
                    for(IR_FuncBlock callFunc:irFuncBlock.getCalledList()){
                        callFunc.getBeCalledList().remove(irFuncBlock);
                    }
                }
            }
            for(IR_FuncBlock irFuncBlock:deletdList){
                this.funcmap.remove(irFuncBlock.get_FuncName());
            }
        }
    }

    //退出块 直接设定函数体里面最后一个基本快设置位退出块 具体优化实现
    public void setExitBlock(IR_Builder builder) {
        for (IR_FuncBlock function : funcmap.values()) {
            getOneBlock(function,builder);
            List<IR_BaseBlock> bb = function.get_bb_List();
            IR_BaseBlock exitBlock = null;
            for (IR_BaseBlock block : bb) {
                for(Instruction instruction : block.get_Instruction_List()){
                    if(instruction instanceof Ret_Instruction){
                        exitBlock = block;
                        break;
                    }
                }
            }
            function.get_bb_List().remove(exitBlock);
            function.get_bb_List().add(exitBlock);
            function.setExitBlock(exitBlock);
        }
    }

    public void getOneBlock(IR_FuncBlock fb,IR_Builder builder){
        IR_Type returnstmt = fb.get_RetType();
        LinkedList<IR_BaseBlock> basicBlocks = fb.get_bb_List();
        for (IR_BaseBlock basicBlock : basicBlocks) {
            boolean isEnd = false;
            List<Instruction> instructions = basicBlock.get_Instruction_List();
            //获取每个 无效的指令集，准备删除
            ArrayList<Instruction> remove = new ArrayList<>();
            for (int count = 0; count < instructions.size(); count++) {
                if (isEnd == false && (instructions.get(count) instanceof Ret_Instruction || instructions.get(count) instanceof Branch_Instruction)) {
                    isEnd = true;
                    continue;
                }
                if (isEnd) {
                    remove.add(instructions.get(count));
                }
            }
            //如果不是end  说明没有遇见 return语句 ，此时需要自己补充
            for (Instruction instruction : remove) {
                instruction.remove();
            }

        }

        //前面删除了所有块在 br和 ret 指令后的所有无效指令，此处获取的 last只能是 br或者 ret
        ArrayList<IR_BaseBlock> exitBlockslist = new ArrayList<>();
        for (IR_BaseBlock basicBlock : basicBlocks) {
            if (basicBlock.get_Instruction_List().getLast() instanceof Ret_Instruction) {
                exitBlockslist.add(basicBlock);
            }
        }

        boolean isVoid = returnstmt == voidType?true:false;

        if (exitBlockslist.size() == 1) {
            fb.setExitBlock(exitBlockslist.get(0));
        } else {
            IR_BaseBlock retbasicBlock = new IR_BaseBlock("retblock",fb);
            fb.addbb(retbasicBlock);
            //第一个块中加入alloca
            IR_Value ret = null;
            //非空的时候
            if (!isVoid) {
                ret = Alloc(builder,returnstmt,"retvalue");
                Instruction instruction = getbuilderbb(builder).get_Instruction_List().getLast();
                getbuilderbb(builder).get_Instruction_List().removeLast();
                int index = 0;
                for(Instruction instruction1 : fb.get_bb_List().get(0).get_Instruction_List()){
                    if((instruction1 instanceof Phi_Instruction)){
                        index++;
                        //不属于 phi 的时候添加
                        //fb.get_bb_List().get(0).get_Instruction_List().add(index,instruction);
                    }
                    else{
                        break;
                    }
                }
                fb.get_bb_List().get(0).get_Instruction_List().add(index,instruction);
                //fb.get_bb_List().get(0).get_Instruction_List().addFirst(instruction);
            }
            for (IR_BaseBlock exitBlock : exitBlockslist) {
                Instruction retInstr = (Ret_Instruction) exitBlock.get_Instruction_List().getLast();
                IR_BaseBlock tmpbb = getbuilderbb(builder);
                setbuilderbb(builder,exitBlock);
                if (!isVoid) {
                    IR_Value store = Store(builder,retInstr.get_op_index(0),ret);
                }
                Br(builder,retbasicBlock);
                exitBlock.getNextBlock().clear();
                IR_Atendwithprenext(exitBlock,retbasicBlock);
                retInstr.remove();
                setbuilderbb(builder,tmpbb);
            }
            IR_BaseBlock tmpbb = getbuilderbb(builder);
            setbuilderbb(builder,retbasicBlock);
            IR_Value loadInstr = null;
            if (!isVoid) {
                loadInstr = Load(builder,"tmp",ret);
            }
            Ret(builder,loadInstr);
            fb.setExitBlock(retbasicBlock);
            setbuilderbb(builder,tmpbb);
        }
    }

    private void clearInstruction(){
        ArrayList<Instruction> deletelist = new ArrayList<>();
        for(IR_FuncBlock funcBlock:this.getFuncBlocks()){
            for(IR_BaseBlock block:funcBlock.get_bb_List()){
                boolean isend = false;
                for(Instruction instruction:block.get_Instruction_List()){
                    if(isend){
                        deletelist.add(instruction);
                        continue;
                    }
                    if(instruction instanceof Ret_Instruction || instruction instanceof Branch_Instruction){
                        isend = true;
                    }
                }
            }
        }

        for(Instruction instruction:deletelist){
            instruction.remove();
        }
    }
    public void buildCFG(){
        clearInstruction();
        //首先清空所有的前驱后继关系
        for (IR_FuncBlock function : funcmap.values()) {
            for(IR_BaseBlock bb : function.get_bb_List()){
                bb.getNextBlock().clear();
                bb.getPreBlock().clear();
            }
        }
        boolean changed = false;
        for (IR_FuncBlock function : funcmap.values()) {
            for(IR_BaseBlock bb : function.get_bb_List()){
                Instruction instruction = bb.get_Instruction_List().getLast();
                if(instruction instanceof Branch_Instruction){
                    if(((Branch_Instruction) instruction).br_type()){
                        // if else
                        IR_BaseBlock bb1 = ((Branch_Instruction) instruction).get_block1();
                        IR_BaseBlock bb2 = ((Branch_Instruction) instruction).get_block2();
                        IR_Atendwithprenext(bb,bb1);
                        IR_Atendwithprenext(bb,bb2);
                    }
                    else{
                        IR_BaseBlock bb1 = ((Branch_Instruction) instruction).get_block1();
                        IR_Atendwithprenext(bb,bb1);
                    }
                }
            }
            List<IR_BaseBlock> deletebb = new ArrayList<>();
            for(IR_BaseBlock bb : function.get_bb_List()){
                if(!bb.getName().contains("Entry") && bb.getPreBlock().size() == 0){
                    //不存在前驱，删除块
                    deletebb.add(bb);
                    changed = true;
                }
            }
            for(IR_BaseBlock bb : deletebb){
                for(Instruction instruction : bb.get_Instruction_List()){
                    instruction.remove();
                }
                for(IR_BaseBlock nxtblock:bb.getNextBlock()){
                    for(Instruction instruction:nxtblock.get_Instruction_List()){
                        if(instruction instanceof Phi_Instruction phiInstruction){
                            phiInstruction.remove_ComingValues(bb);
                        }
                        else{
                            break;
                        }
                    }
                    nxtblock.getPreBlock().remove(bb);
                }
                function.get_bb_List().remove(bb);
            }
        }
        if(changed){
            buildCFG();
        }
    }

    public void calc_CallRelation() {
        ArrayList<IR_FuncBlock> funcs = new ArrayList<>(funcmap.values());
        for (IR_FuncBlock function : funcs) {
            function.getCalledList().clear();
            function.getBeCalledList().clear();
        }
        for (IR_FuncBlock function : funcs) {
            LinkedList<IR_BaseBlock> baseBlocks = function.get_bb_List();
            for (IR_BaseBlock block : baseBlocks) {
                LinkedList<Instruction> instructions = block.get_Instruction_List();
                for (Instruction instruction : instructions) {
                    if (instruction instanceof Call_Instruction) {
                        IR_FuncBlock callFunction = ((Call_Instruction) instruction).get_funcBlock();
                        if (!callFunction.isLib() && !callFunction.getBeCalledList().contains(function)) {
                            callFunction.getBeCalledList().add(function);
                        }
                        if (!callFunction.isLib() && !function.getCalledList().contains(callFunction)) {
                            function.getCalledList().add(callFunction);
                        }
                    }
                }
            }
        }
    }

    // 判断一个指令返回的IR_Value是否在Module中被引用，若被引用，出现次数需要大于等于2（包括被计算出来的一次）
    public boolean is_Dead_Ins(Instruction instruction) {
        // System.out.println(oldValue.get_ValueName() + " -> " + newValue.get_ValueName());
        if (instruction instanceof Call_Instruction) {
            IR_FuncBlock called_Func = ((Call_Instruction) instruction).get_funcBlock();
            if (called_Func.isSideEffect() || called_Func.get_RetType() instanceof IR_Void){
                return false;
            }
        }

        if (instruction instanceof Ret_Instruction || instruction instanceof Store_Instruction || instruction instanceof Branch_Instruction) {
            return false;
        }

        IR_Value value = instruction.get_op().get(0);
        if(instruction instanceof Move_Instruction){
            value = ((Move_Instruction) instruction).get_op().get(1);
        }
        ArrayList<IR_FuncBlock> funcs = this.getFuncBlocks();
        //if (instruction instanceof )
        //System.out.println("遍历前: " + System.identityHashCode(funcs));
        for (IR_FuncBlock functionBlock : funcs) {
            //System.out.println(("遍历后： " + System.identityHashCode(funcs)));
            for (IR_BaseBlock block : functionBlock.get_bb_List()) {
                for (Instruction ins : block.get_Instruction_List()) {
                    if (ins == instruction)
                    {
                        continue;
                    }
                    List<IR_Value> op = ins.get_op();
                    // 处理phi指令处的引用
                    if (ins instanceof Phi_Instruction phiInstruction) {
                        for (IR_BaseBlock key : phiInstruction.get_ComingValues().keySet()) {
                            if (phiInstruction.get_ComingValues().get(key).equals(value)) {
                                return false;
                            }
                        }
                    }

                    //处理call函数参数处的引用
                    if (ins instanceof Call_Instruction callInstruction) {
                        for (int k = 0; k < callInstruction.get_params().size(); k++) {
                            if (callInstruction.get_params().get(k).equals(value)) {
                                return false;
                            }
                        }
                    }

                    for (int k = 0; k < op.size(); k++) {
                        if (op.get(k) == null) {
                            continue;
                        }
                        if (op.get(k).get_ValueName().equals(value.get_ValueName())) {
                            return false;
                        }
                    }
                }
            }
        }
        return true;
    }


    public void replaceUse(IR_Value oldValue, IR_Value newValue) {
        // System.out.println(oldValue.get_ValueName() + " -> " + newValue.get_ValueName());
        ArrayList<IR_FuncBlock> funcs = this.getFuncBlocks();
        //System.out.println("遍历前: " + System.identityHashCode(funcs));
        for (IR_FuncBlock functionBlock : funcs) {
            //System.out.println(("遍历后： " + System.identityHashCode(funcs)));
            for (IR_BaseBlock block : functionBlock.get_bb_List()) {
                for (Instruction ins : block.get_Instruction_List()) {
                    List<IR_Value> op = ins.get_op();

                    // 处理phi指令处的引用
                    if (ins instanceof Phi_Instruction phiInstruction) {
                        for (IR_BaseBlock key : phiInstruction.get_ComingValues().keySet()) {
                            if (phiInstruction.get_ComingValues().get(key).equals(oldValue)) {
                                phiInstruction.set_ComingValue(newValue, key);
                            }
                        }
                    }

                    //处理call函数参数处的引用
                    if (ins instanceof Call_Instruction callInstruction) {
                        for (int k = 0; k < callInstruction.get_params().size(); k++) {
                            if (callInstruction.get_params().get(k).equals(oldValue)) {
                                callInstruction.setParams(k, newValue);
                            }
                        }
                    }

                    for (int k = 0; k < op.size(); k++) {
                        if (op.get(k) == null) {
                            continue;
                        }
                        if (op.get(k).get_ValueName().equals(oldValue.get_ValueName())) {
                            if (ins instanceof Pointer_Instruction) {
                                // debug
                                if(k>=2) {
                                    ((Pointer_Instruction) ins).set_List(k - 2, newValue);
                                }
                                if(k==1){
                                    ((Pointer_Instruction) ins).set_Base(newValue);
                                }
                                ins.set_Op(k, newValue);
                            } else if (ins instanceof Type_Trans_Instruction) {
                                // 对类型转换指令进行特殊的处理
                                if (k == 0) {
                                    ((Type_Trans_Instruction) ins).set_Res(newValue);
                                } else if (k == 1) {

                                    ((Type_Trans_Instruction) ins).set_Origin(newValue);
                                }
                                ins.set_Op(k, newValue);
                            }
                            else{
                                ins.set_Op(k, newValue);
                            }
                        }
                    }
                }
            }
        }
    }

    public void genRelation(){
        //初始化调用函数链  同时也实现了 set tail
        buildCallRelation();
        setfuncTail();
        //删除无用的函数 没有被调用的
        removeNoCallFunc();
        //生成 CFG 图
        buildCFG();
        //testCFGbyBlocksPreSucee(visitor.get_module());\
    }

    public void simplyBBRelation(){
        buildCFG();
        bbopt = new HashMap<>();
        for(IR_FuncBlock funcBlock:getFuncBlocks()){
            ArrayList<Branch_Instruction> deletelist = new ArrayList<>();
            for(IR_BaseBlock block:funcBlock.get_bb_List()){
                if(!block.getName().contains(funcBlock.get_FuncName())){
                    //函数入口块不删除
                    if(block.get_Instruction_List().size() == 1 && block.get_Instruction_List().getFirst() instanceof Branch_Instruction branchInstruction){
                        deletelist.add(branchInstruction);
                        bbopt.put(branchInstruction.get_bb(),branchInstruction.get_block1());
                    }
                }
            }
            for(Branch_Instruction branchInstruction:deletelist){
                deleteblock(funcBlock,branchInstruction);
                buildCFG();
            }
        }
    }

    private void deleteblock(IR_FuncBlock funcBlock,Branch_Instruction instruction){
        if(instruction.br_type()){
            return;
        }
        IR_BaseBlock toblock = instruction.get_block1();
        IR_BaseBlock nowblock = instruction.get_bb();
        for(IR_BaseBlock preblock:nowblock.getPreBlock()){
            if(preblock.get_Instruction_List().getLast() instanceof Branch_Instruction branchInstruction){
                if(branchInstruction.get_block1().equals(nowblock)){
                    branchInstruction.setBlock1(toblock);
                    dealwithNxtPhi(preblock,nowblock);
                }
                if(branchInstruction.br_type() && branchInstruction.get_block2().equals(nowblock)){
                    branchInstruction.setBlock2(toblock);
                    dealwithNxtPhi(preblock,nowblock);
                }
            }
        }
        funcBlock.get_bb_List().remove(nowblock);
    }

    private void dealwithNxtPhi(IR_BaseBlock preblock,IR_BaseBlock nowblock){
        for(IR_BaseBlock nxt: nowblock.getNextBlock()){
            for(Instruction instruction: nxt.get_Instruction_List()){
                if(instruction instanceof Phi_Instruction phiInstruction){
                    if(phiInstruction.get_ComingValues().containsKey(nowblock)){
                        IR_Value value = phiInstruction.get_ComingValues().get(nowblock);
                        phiInstruction.remove_ComingValues(nowblock);
                        phiInstruction.set_ComingValue(value,preblock);
                    }
                }else{
                    break;
                }
            }
        }
    }

    public void mergeBB() {
        buildCFG();
        for (IR_FuncBlock funcBlock : getFuncBlocks()) {
            ArrayList<IR_BaseBlock> deletelist = new ArrayList<>();
            int z = 0;
            for (int i = z; i < funcBlock.get_bb_List().size(); i++) {
                IR_BaseBlock block = funcBlock.get_bb_List().get(i);
                if (block.getNextBlock().size() == 1 && block.getNextBlock().get(0).getPreBlock().size() == 1) {
                    IR_BaseBlock nextblock = block.getNextBlock().get(0);
                    deletelist.add(nextblock);
                    ArrayList<IR_BaseBlock> nextblocklist = new ArrayList<>();
                    nextblocklist.addAll(nextblock.getNextBlock());
                    for (IR_BaseBlock bb : nextblocklist) {
                        IR_deletewithprenext(nextblock, bb);
                        IR_Atendwithprenext(block, bb);
                    }
                    IR_deletewithprenext(block, nextblock);

                    block.get_Instruction_List().removeLast();
                    for (Instruction instruction : nextblock.get_Instruction_List()) {
                        instruction.set_bb(block);
                        block.get_Instruction_List().add(instruction);
                    }
                    break;
                }
                z++;
            }
            for (IR_BaseBlock bb : deletelist) {
                funcBlock.get_bb_List().remove(bb);
            }
            updateExitblock(funcBlock);
        }
    }

    private void updateExitblock(IR_FuncBlock funcBlock){
        for(IR_BaseBlock bb:funcBlock.get_bb_List()) {
            Instruction instruction = bb.get_Instruction_List().getLast();
            if (instruction instanceof Ret_Instruction) {
                funcBlock.setExitBlock(bb);
                break;
            }
        }
    }

    // 寻找value是哪一条指令的结果
    public Instruction find_Instruction_InModule(IR_Value value) {
        for (IR_FuncBlock functionBlock : this.getFuncBlocks()) {
            for (IR_BaseBlock block : functionBlock.get_bb_List()) {
                for (Instruction ins : block.get_Instruction_List()) {
                    List<IR_Value> op = ins.get_op();
                    if (op.get(0) == null) {
                        // 针对ret void指令进行处理
                        return null;
                    }
                    if (ins.get_op().get(0).equals(value)) {
                        return ins;
                    }
                }
            }
        }
        return null;
    }

    public void constantPropagationForGlobalVars() {
        //  收集所有常量全局变量
        Map<String, IR_Value> constGlobals = new HashMap<>();
        Map<String,IR_Value> globalvarmap = new HashMap<>();
        Map<IR_Value,IR_Value> replaceMap = new HashMap<>();

        for (IR_Global_Value global : globalVars) {
            String globalName = global.get_Global_Identity();
            IR_Value initValue = gloabal_Varmap.get(globalName);
            // 只处理基本类型常量（整数/浮点数）
            if (initValue instanceof IR_Int_Value || initValue instanceof IR_Float_Value) {
                constGlobals.put(global.get_ValueName(), initValue);
                globalvarmap.put(global.get_ValueName(),global);
            }
        }

        // 检测哪些全局变量被修改过
        detectModifiedGlobals(constGlobals,globalvarmap);

        ArrayList<Instruction> deletelist = new ArrayList<>();
        for(IR_FuncBlock funcBlock:getFuncBlocks()){
            for (IR_BaseBlock bb : funcBlock.get_bb_List()) {
                for (Instruction ins : bb.get_Instruction_List()) {
                    if (ins instanceof Load_Instruction loadInstruction && globalvarmap.containsValue(loadInstruction.getPointer())) {
                        deletelist.add(loadInstruction);
                        String key = ((IR_Global_Value)loadInstruction.getPointer()).get_Global_Identity();
                        replaceMap.put(loadInstruction.getRet(),gloabal_Varmap.get(key));
                    }
                }
            }
        }

        for(Map.Entry<IR_Value, IR_Value> entry: replaceMap.entrySet()){
            for(IR_FuncBlock funcBlock:getFuncBlocks()){
                funcBlock.replaceUseInFunc(entry.getKey(),entry.getValue());
            }
        }

        for (Instruction instruction : deletelist) {
            instruction.remove();
        }
    }

    private void detectModifiedGlobals(Map<String, IR_Value> constGlobals,Map<String,IR_Value> globalvarmap){
        for(IR_FuncBlock funcBlock: getFuncBlocks()){
            for(IR_BaseBlock bb: funcBlock.get_bb_List()){
                for(Instruction ins: bb.get_Instruction_List()){
                    if(ins instanceof Store_Instruction storeInstruction){
                        if(constGlobals.containsKey(storeInstruction.getPointer().get_ValueName())){
                            constGlobals.remove(storeInstruction.getPointer().get_ValueName());
                            globalvarmap.remove(storeInstruction.getPointer().get_ValueName());
                        }
                    }
                }
            }
        }
    }

    public void deleteInaccessibleBB(){
        for(IR_FuncBlock funcBlock:getFuncBlocks()){
            Set<IR_BaseBlock> s = new HashSet<>();
            LinkedList<IR_BaseBlock> blocks = new LinkedList<>();
            blocks.add(funcBlock.get_bb_List().get(0));
            s.add(funcBlock.get_bb_List().get(0));
            while (!blocks.isEmpty()) {
                IR_BaseBlock bb = blocks.getFirst();
                blocks.removeFirst();
                for(IR_BaseBlock nex:bb.getNextBlock()){
                    if(!s.contains(nex)){
                        s.add(nex);
                        blocks.add(nex);
                    }
                }
            }
            ArrayList<IR_BaseBlock> deletelist = new ArrayList<>();
            for(IR_BaseBlock bb:funcBlock.get_bb_List()){
                if(!s.contains(bb)){
                    deletelist.add(bb);
                }
            }
            for(IR_BaseBlock bb:deletelist){
                ArrayList<IR_BaseBlock> ll = new ArrayList<>(bb.getNextBlock());
                for(IR_BaseBlock nex:ll){
                    IR_deletewithprenext(bb,nex);
                    for(Instruction ins:nex.get_Instruction_List()){
                        if(ins instanceof Phi_Instruction phiInstruction){
                            if(phiInstruction.get_ComingValues().containsKey(bb)){
                                phiInstruction.remove_ComingValues(bb);
                            }
                        }
                    }
                }
                funcBlock.get_bb_List().remove(bb);
            }
        }
    }
}
